import { createDiscreteApi } from "naive-ui";
import type { CustomRequestOptions } from "naive-ui/es/upload/src/interface";
import Base64 from "crypto-js/enc-base64";
import CryptoJS from "crypto-js";
import { v4 } from "uuid";
import { ref } from "vue";
import localforage from "localforage";
export const usePreChat = () => {
  const preChatLists = ref<(string | FileSystemFileHandle)[]>([]);
  const exportChatLists = useMyLocalStorage<any[]>("exportChatLists", []);
  const page = ref(1);
  const pageSizes = 10;
  const tabIndex = ref(0);
  const loading = ref(false);
  const tableData = ref<any[]>([]);
  const pageCount = ref(0);
  const upload = ref();
  watch(
    () => tabIndex.value,
    () => {
      pageCount.value = !tabIndex.value
        ? Math.ceil(preChatLists.value.length / pageSizes + 1) - 1
        : Math.ceil(exportChatLists.value.length / pageSizes + 1) - 1;
    }
  );
  const handlePageChange = async (pageNo: number) => {
    loading.value = true;
    page.value = pageNo;
    tableData.value = [];
    if (tabIndex.value === 1) {
      tableData.value = exportChatLists.value.slice(
        (pageNo - 1) * pageSizes,
        (pageNo - 1) * pageSizes + pageSizes
      );
    } else {
      const page = preChatLists.value.slice(
        (pageNo - 1) * pageSizes + 1,
        (pageNo - 1) * pageSizes + pageSizes + 1
      );
      let contents: string[] = [];
      if (Tauri.isTauri()) {
        contents = (await Tauri.readFilesContents(page as string[])) ?? [];
      } else {
        for (let i = 0; i < page.length; i++) {
          const res = (
            await (page as FileSystemFileHandle[])[i].getFile()
          ).text();
          contents.push(await res);
        }
      }
      tableData.value = contents.map((item) => JSON.parse(item));
    }
    loading.value = false;
  };
  const tabsUpdate = async (key: number) => {
    if (key === 1) {
      await handlePageChange(1);
    }
    if (key === 0) {
      await handlePageChange(1);
    }
  };
  const exportPreChat = (options: CustomRequestOptions) => {
    const file = options.file.file;
    const fileType = file!.type;
    const readerJson = new FileReader();
    readerJson.readAsText(file!);
    let charaInfo = {} as any;
    readerJson.onload = async () => {
      const result = readerJson.result as string;
      if (fileType === "image/png") {
        const charaIndex = result.indexOf("chara");
        const doubleQualsIndex = result.indexOf("==", charaIndex);
        charaInfo = result.slice(charaIndex + 6, doubleQualsIndex + 2).trim();
        const readerImg = new FileReader();
        readerImg.readAsDataURL(file!);
        readerImg.onload = async () => {
          const result = readerImg.result as string;
          exportChatLists.value.push({
            ...JSON.parse(Base64.parse(charaInfo).toString(CryptoJS.enc.Utf8)),
            avatar: result,
          });
          await handlePageChange(1);
        };
      } else if (fileType === "application/json") {
        exportChatLists.value.push(JSON.parse(result as string));
        await handlePageChange(1);
      }
    };
  };

  const deletePreChat = async (row: any) => {
    exportChatLists.value = exportChatLists.value.filter(
      (chat) => chat.name !== row.name
    );
    await handlePageChange(1);
  };

  const selectRow = ref();
  const { setChat } = chatStore();
  const { chatMap, currentChat } = storeToRefs(chatStore());
  const { getSetValue, setSetValue } = chatSettingStore();
  // 对预设对话进行处理
  const settingsHandler = (settings: any, preChat: any) => {
    const systemPrompt = [
      "main",
      "nsfw",
      "dialogueExamples",
      "jailbreak",
      "worldInfoAfter",
      "worldInfoBefore",
      "enhanceDefinitions",
      "charDescription",
      "charPersonality",
      "scenario",
      "personaDescription",
    ];
    const result = {} as Record<string, Message>;
    settings.prompt_order[0].order.map((e: any) => {
      if (!e.enabled) return;
      let prompt = settings.prompts.find(
        (i: { identifier: any }) => i.identifier === e.identifier
      );
      if (systemPrompt.includes(prompt.identifier)) {
        const promptMap: any = {
          charPersonality: "personality",
          charDescription: "description",
          personaDescription: "persona",
          scenario: "scenario",
          dialogueExamples: "examples",
          jailbreak: "jailbreak",
        };
        if (preChat.definition?.[promptMap[prompt.identifier]]) {
          prompt!.content = preChat.definition[promptMap[prompt.identifier]];
        }
        if (preChat[promptMap[prompt.identifier]]) {
          prompt!.content = preChat[promptMap[prompt.identifier]];
        }
      }
      const id = v4();
      if (prompt!.content || prompt.identifier === "chatHistory") {
        prompt!.content = prompt!.content?.replace(
          /{{char}}/g,
          preChat.definition?.project_name ?? preChat?.name
        );
        prompt!.content = prompt!.content?.replace(
          /{{user}}/g,
          getSetValue("base")("username") ?? "我"
        );
        result[id] = {
          content: prompt!.content,
          role: "system",
          id,
          identifier: prompt.identifier,
          type: "preChat",
        };
      }
      return result;
    });
    const new_chat_promptId = v4();
    if (settings.new_chat_prompt) {
      result[new_chat_promptId] = {
        content: settings?.new_chat_prompt ?? "[Start a new Chat]",
        role: "system",
        id: new_chat_promptId,
        identifier: "new_chat_prompt",
        type: "preChat",
      };
    }
    const map: Record<string, string> = {
      first_mes: "first_mes",
    };
    IterationObject(selectRow.value, (key, value) => {
      if (map[key]) {
        const id = v4();
        if (key === "first_mes") {
          result[id] = {
            content: value as string,
            role: "assistant",
            id,
            identifier: key,
            type: "chat",
          };
        }
      }
    });
    return result;
  };
  const { message } = createDiscreteApi(["message"]);
  const createChat = () => {
    if (!getSetValue("generate")("setting")[0]?.url) {
      message.error("请先设置生成配置");
      return;
    }
    const chatId = setChat().id;
    const chat = chatMap.value.get(chatId);
    const settings = JSON.parse(getSetValue("generate")("setting")[0]?.url);
    const messages = settingsHandler(settings, selectRow.value);
    chat!.messages = messages;
    chat!.name =
      selectRow.value.definition?.project_name ?? selectRow.value?.name;
    chat!.user = {
      name: selectRow.value.definition?.project_name ?? selectRow.value?.name,
      avatar: selectRow.value.definition?.avatar ?? selectRow.value?.avatar,
    };
    currentChat.value = chatId;
    return chatId;
  };
  const selectLocal = async () => {
    const local = (await Tauri.dialogOpen({
      title: "选择文件",
      filters: [{ name: "所有文件", extensions: ["*"] }],
      directory: true,
      multiple: false,
    })) as string;
    setSetValue("generate", "preChatListPath", local);
    preChatLists.value = await Tauri.getFilesPath(local);
    await handlePageChange(1);
  };
  const handleSelect = (e: string) => {
    if (e === "selectLocal") {
      selectLocal();
    }
    if (e === "export") {
      upload.value?.openOpenFileDialog();
    }
  };
  const init = async () => {
    if (getSetValue("generate")("preChatListPath")) {
      if (Tauri.isTauri()) {
        preChatLists.value = await Tauri.getFilesPath(
          getSetValue("generate")("preChatListPath")
        );
      } else {
        const directoryHandlerMap = (await localforage.getItem(
          "DirectoryHandlerMap"
        )) as Record<string, FileSystemDirectoryHandle>;
        const directoryHandler =
          directoryHandlerMap.preChatListPath;
        for await (const entry of (directoryHandler as any).values()) {
          preChatLists.value.push(entry as FileSystemFileHandle);
        }
      }
      pageCount.value = Math.ceil(preChatLists.value.length / page.value) - 1;
    }
    handlePageChange(1);
  };
  return {
    preChatLists: getSetValue("generate")("preChatListPath"),
    init,
    tabIndex,
    tabsUpdate,
    handleSelect,
    exportPreChat,
    tableData,
    selectRow,
    createChat,
    pageCount,
    loading,
    handlePageChange,
    deletePreChat,
    page,
  };
};
